/*
 * @Author: zi.yang
 * @Date: 2024-11-06 16:02:11
 * @LastEditors: zi.yang
 * @LastEditTime: 2024-11-07 10:30:49
 * @Description:
 * @FilePath: /save-gitee-img/index.js
 */
import {
  accessSync,
  existsSync,
  mkdirSync,
  readFileSync,
  writeFileSync,
} from 'node:fs';

import { apiList, defaultFileNameHandle, defaultProps } from './api.js';
import GiteeApi from './GiteeApi.js';

const giteeApi = new GiteeApi();

const commonHeader = {
  accept: '*/*',
  'accept-language': 'zh-CN,zh;q=0.9',
  'cache-control': 'no-cache',
  pragma: 'no-cache',
  priority: 'u=1, i',
  'sec-ch-ua': '"Not?A_Brand";v="99", "Chromium";v="130"',
  'sec-ch-ua-mobile': '?0',
  'sec-ch-ua-platform': '"macOS"',
  'sec-fetch-dest': 'empty',
  'sec-fetch-mode': 'cors',
  'sec-fetch-site': 'cross-site',
  'user-agent':
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (537.36) Chrome/130.0.0.0 Safari/537.36',
};

let cacheContent = new Set();
try {
  if (!existsSync('./cache.json')) {
    writeFileSync('./cache.json', '[]');
  }
  const cacheUploadFile = readFileSync('./cache.json', 'utf-8') || '[]';
  cacheContent = new Set(JSON.parse(cacheUploadFile));
} catch (e) {
  console.error('缓存读取失败：', e.toString());
  process.exit(1);
}

/**
 * fetch 请求
 * @param {*} url
 * @param {*} data
 * @param {*} method
 * @returns
 */
function fetchApi(url, data, method) {
  const _url = url;
  return fetch(_url, {
    headers: commonHeader,
    body: method === 'POST' ? JSON.stringify(data) : null,
    method: 'GET',
    mode: 'cors',
    credentials: 'omit',
  });
}


function ensureDirectoryExists(path) {
  try {
    accessSync(path);
  } catch {
    mkdirSync(path, { recursive: true });
  }
}

/**
 * 请求图片数据
 * @param {*} param0 
 * @returns 
 */
async function fetchImage({ url, props = defaultProps, fileNameHandler = defaultFileNameHandle }) {
  // 获取图片地址
  const dataInfo = await fetchApi(url, {}, 'GET').then((res) => res.json());
  const imgUrl = dataInfo[props.url];
  if (cacheContent.has(imgUrl)) return null;
  if (!imgUrl) {
    console.log('图片接口请求报错： ', dataInfo[props.msg]);
    return null;
  }
  // 获取图片二进制数据
  const arrayBuffer = await fetchApi(imgUrl).then((res) => res.arrayBuffer());
  const fileName = fileNameHandler(imgUrl);
  cacheContent.add(imgUrl);
  return { fileName, buffer: Buffer.from(arrayBuffer), };
}

/**
 * 保存到本地磁盘
 * @param {*} param0 
 * @returns 
 */
function saveToDisk({ type, fileName, buffer }) {
  return new Promise((resolve, reject) => {
    try {
      const { DISK_SAVE_PATH } = process.env;
      const target = DISK_SAVE_PATH.endsWith('/') ? DISK_SAVE_PATH : `${DISK_SAVE_PATH}/`;
      ensureDirectoryExists(`${target}${type}`)
      writeFileSync(`${target}${type}/${fileName}`, buffer)
      resolve(true);
    } catch (e) {
      console.log(e);
      reject({ message: e.toString() })
    }
  });
}

let apiIndex = 0;
let saveCount = 0;
/**
 * 定时上传图片任务
 * @param { number } time
 */
function runFetchTimer(time) {
  function _run() {
    const { type } = apiList[apiIndex];
    fetchImage(apiList[apiIndex])
      .then((data) => {
        if (!data) return null;
        const msg = new Date().toLocaleString() + ' 获取到图片';
        if (process.env.SAVE_TARGET === 'DISK') return saveToDisk({ ...data, type });
        return giteeApi.uploadImage(`/${type}/${data.fileName}`, data.buffer.toString('base64'), msg);
      })
      .then((res) => {
        if (!res) return;
        if (res.message) {
          console.log('文件保存失败：', res.message);
        } else {
          console.log(`文件保存成功, 本次任务总共保存：${++saveCount} 个, 累计保存：${cacheContent.size} 个`);
        }
        writeFileSync('./cache.json', JSON.stringify(Array.from(cacheContent)), 'utf-8');
      })
      .catch((e) => {
        console.log('执行保存报错：', e.toString());
      })
      .finally(() => {
        apiIndex = (apiIndex + 1) % apiList.length;
        runFetchTimer(1000);
      });
  }
  time ? setTimeout(_run, time) : _run();
}

runFetchTimer();
